

#region Using Statements
using System;
using System.Collections.Generic;
//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion


namespace Pauliver
{

    public interface GameManagerTeamedInterface
    {
        void ProcessInput(PlayerObject Current, PlayerIndex controller);

        void Update(GameTime p_time);

        //void FakeSwitchTeam(GameTime p_time, bool CanShoot);

        //void SwitchTeam(GameTime p_time, bool CanShoot);

        void Draw(SpriteBatch p_SpriteBatch, GameTime p_GameTime, Rectangle p_Screen);

        PlayerIndex CurrentPlayer();

        bool MyMachineIsActive();

        bool CanChangeTeam();
        void SetCanChangeTeam(bool value);

        UserTeamPlayer CurrentUTP();
    }

    public class GameManagerTeamed : GameManager, GameManagerTeamedInterface
    {
        protected String TestMessage;
        
        //The PlayerTeamManager and the UserTeamManager
        //Should be rolled together into one class
        //With a "Network" option
        //protected PlayerTeamManager po;
        //protected UserTeamManagement<PlayerIndex> pi;

        protected UserTeamPlayerManager UTPM;

        protected int playercount = 0;
        protected int TeamCount;
        protected float TurnStart;
        protected const int SL = 32;
        protected GameTime LastGameTime;
        protected bool GameStarted = false;

        protected AI ai;

        protected bool m_ChangeTeam = true;

        public UserTeamPlayer CurrentUTP()
        {
            return UTPM.Current;
        }

        public bool CanChangeTeam()
        {
            return m_ChangeTeam;
        }
        public void SetCanChangeTeam(bool value)
        {
            m_ChangeTeam = value;
        }

        public GameManagerTeamed(List<Triplet<Team,PlayerIndex,TeamType> > teams,DynamicLevel level, BaseCollision Collision)
            : base(level, Collision)
        {
            NetworkManager.Instance.Disconnect();
            ai = null;
            GameStarted = false;
            TeamCount = teams.Count;
            playercount = 3 * teams.Count;
            //po = new PlayerTeamManager();
            //pi = new UserTeamManagement<PlayerIndex>();

            UTPM = new UserTeamPlayerManager();

            for (int i = 0; i < teams.Count; ++i)
            {
                //po.AddTeam(teams[i].First);
                //pi.AddTeam(teams[i].First);
                //pi.AddPlayerToTeam(teams[i].First, teams[i].Second);
                UTPM.AddTeam(teams[i].First,teams[i].Third);
                UTPM.AddPlayerToTeam(teams[i].First, teams[i].Second);
            }
            TurnStart = 0;
            SetupPlayers();

            TestMessage = "Welcome";

            EventManager.GetInstance().AddEvent(ClearText, 1.5f);
            
            //the below should be replaced with a CanShoot in the Weapon object not just its input shoot component
            //OR we need to define an Input_Shoot_Other component that subclasses from Input_Shoot...
            ((UTPM.CurrentAvatar[ComponentType.Holder_Weapon] as Holder_Weapon).Weapon[ComponentType.Input_Shoot] as Input_Shoot).CanShoot = true;


            timefont = PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/TimeFont");
            invader = PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/Irken");
            target = PContentManager.Instance.GetObject<Texture2D>(@"Content/Art/Sprites/Reticle");
        }

        public virtual void SetupPlayers()
        {
            //base.SetupPlayers();
            int spacing = (int) (Game1.Instance.World.Y - (Terrain.tolerance * 2)) / playercount;
            List<Team> teams = UTPM.GetTeams();
            int CurrentIndex = 0;
            for (int i = 0; i < playercount; i++)
            {
                PlayerObject poi = new PlayerObject();
                (poi[ComponentType.Game_Position] as Game_Position).X += Terrain.tolerance + (i*2) * spacing;
                (poi[ComponentType.Game_Position] as Game_Position).Y = (Level as DynamicLevel)[(int)(poi[ComponentType.Game_Position] as Game_Position).X] - 16;

                poi.AddComponent(new Game_Team(teams[CurrentIndex]));
                PlayerHitpoints ph = new PlayerHitpoints(poi);
                UTPM.AddAvatarToTeam(teams[CurrentIndex], poi);

                base._SceneGraph.Add(poi);
                base._SceneGraph.Add(ph);
                
                if (++CurrentIndex >= teams.Count)
                {
                    CurrentIndex = 0;
                }
            }

            //po.Setup();
            //pi.Setup();
            UTPM.Setup();
            Game1.Instance.CenterOn((UTPM.CurrentAvatar[ComponentType.Game_Position] as Game_Position).Position);
        }

        public virtual void ProcessInput(PlayerObject Current, PlayerIndex controller)
        {
            UTPM.CurrentAvatar.ProcessInput(UTPM.CurrentPlayer);
        }

        public bool MyMachineIsActive()
        {
            return true;
        }

        float TimeStep = 0.0f;
        public override void Update(GameTime p_time)
        {
            LastGameTime = p_time;
            if (!GameStarted)
            {
                SwitchTeam(p_time, true);
                GameStarted = true;
            }

            if (UTPM.GetWinningTeam() != Team.NoTeam)
            {
                Game1.Instance.AddMenu(new GameOver(UTPM.GetWinningTeam()));
                Game1.Instance.EndGame();
                return;
            }

            TimeStep = (float)p_time.TotalGameTime.TotalSeconds - TurnStart;
            //if(CanChangeTeam == false || Game1.Instance.CurrentMenu != null)
            //{
            //    TurnStart += (float)( p_time.ElapsedRealTime.Milliseconds * .001);
            //}
            if ((TimeStep >= SL) && m_ChangeTeam && AllowInput)
            {
                SwitchTeam(p_time,true);
                TimeStep = 0.0f;
            }

            if (UTPM.Current.TeamType == TeamType.AI)
            {
                if (ai != null && AllowInput)
                {
                    ai.Update(TimeStep);
                }
            }

            if (m_ChangeTeam && AllowInput)
            {
                if (PInput.Instance.GamePad(UTPM.CurrentPlayer).Back.State == InputWrapper.ButtonState.Pressed)
                {//Advance to Team and Next Player   
                    SwitchTeam(p_time,true);
                }
           
#if WINDOWS
                if (PInput.Instance.Keyboard.Enter.State == InputWrapper.ButtonState.Pressed)
                {//Advance to Team and Next Player   
                    SwitchTeam(p_time,true);
                }
#endif
            }

            if (AllowInput)
            {
                if (Game1.Instance.CurrentMenu == null)
                {
                    ProcessInput(UTPM.CurrentAvatar, UTPM.CurrentPlayer);
                }
                else
                {
                    Game1.Instance.CurrentMenu.ProccessInput(UTPM.CurrentPlayer);
                }
            }

            if ((UTPM.CurrentAvatar[ComponentType.Collidable] as Collidable).Moving)
            {
                Game1.Instance.CenterOn((UTPM.CurrentAvatar[ComponentType.Game_Position] as Game_Position).Position);
            }

            base.Update(p_time);
        }

        public virtual void FakeSwitchTeam2(GameTime p_time, bool CanShoot)
        {
            (UTPM.CurrentAvatar[ComponentType.Drawable_Sprite_Animated] as Drawable_Sprite_Animated).SetCurrentAnimation("Idle" + UTPM.CurrentAvatar.GetFacing());
            TurnStart = (int)p_time.TotalGameTime.TotalSeconds;
            // Dont' advance, we did this allready //UTPM.AdvancePlayerOnly();
            Holder_Weapon hw = (UTPM.CurrentAvatar[ComponentType.Holder_Weapon] as Holder_Weapon);
            if (hw != null)
            {
                (hw.Weapon[ComponentType.Input_Shoot] as Input_Shoot).CanShoot = CanShoot;
            }
            if (Game1.Instance.CurrentMenu != null)
            {
                Game1.Instance.PopTopMenu();
            }
            Game1.Instance.SlideTowards((UTPM.CurrentAvatar[ComponentType.Game_Position] as Game_Position).Position);

            if (UTPM.Current.TeamType == TeamType.AI)
            {
                ai = new SmarterAI((FakeGamePad)PInput.Instance.GamePad(UTPM.CurrentPlayer), UTPM,SceneGraph);
            }
            else
            {
                ai = null;
            }

            TestMessage = UTPM.CurrentTeam + "'s Turn";
            AllowInput = false;
            EventManager.GetInstance().AddEvent(ClearText,1.5f);
        }
        
        public virtual void FakeSwitchTeam(GameTime p_time,bool CanShoot)
        {
            (UTPM.CurrentAvatar[ComponentType.Drawable_Sprite_Animated] as Drawable_Sprite_Animated).SetCurrentAnimation("Idle" + UTPM.CurrentAvatar.GetFacing());
            TurnStart = (int)p_time.TotalGameTime.TotalSeconds;
            UTPM.AdvancePlayerOnly();
            Holder_Weapon hw = (UTPM.CurrentAvatar[ComponentType.Holder_Weapon] as Holder_Weapon);
            if (hw != null)
            {
                (hw.Weapon[ComponentType.Input_Shoot] as Input_Shoot).CanShoot = CanShoot;
            }
            if(Game1.Instance.CurrentMenu != null)
            {
                Game1.Instance.PopTopMenu();
            }
            Game1.Instance.SlideTowards((UTPM.CurrentAvatar[ComponentType.Game_Position] as Game_Position).Position);

            if (UTPM.Current.TeamType == TeamType.AI)
            {
                ai = new SmarterAI((FakeGamePad)PInput.Instance.GamePad(UTPM.CurrentPlayer),UTPM,_SceneGraph);
            }
            else
            {
                ai = null;
            }

            TestMessage = UTPM.CurrentTeam + "'s Turn";
            AllowInput = false;
            EventManager.GetInstance().AddEvent(ClearText, 1.5f);
        }
        
        public virtual void SwitchTeam(GameTime p_time,bool CanShoot)
        {
            (UTPM.CurrentAvatar[ComponentType.Drawable_Sprite_Animated] as Drawable_Sprite_Animated).SetCurrentAnimation("Idle" + UTPM.CurrentAvatar.GetFacing());
            TurnStart = (int)p_time.TotalGameTime.TotalSeconds;
            UTPM.Advance();
            Holder_Weapon hw = (UTPM.CurrentAvatar[ComponentType.Holder_Weapon] as Holder_Weapon);
            if (hw != null)
            {
                (hw.Weapon[ComponentType.Input_Shoot] as Input_Shoot).CanShoot = CanShoot;
            }
            if(Game1.Instance.CurrentMenu != null)
            {
                Game1.Instance.PopTopMenu();
            }
            Game1.Instance.SlideTowards((UTPM.CurrentAvatar[ComponentType.Game_Position] as Game_Position).Position);

            if (UTPM.Current.TeamType == TeamType.AI)
            {
                ai = new SmarterAI((FakeGamePad)PInput.Instance.GamePad(UTPM.CurrentPlayer), UTPM, _SceneGraph);
            }
            else
            {
                ai = null;
            }

            TestMessage = UTPM.CurrentTeam + "'s Turn";
            AllowInput = false;
            EventManager.GetInstance().AddEvent(ClearText,1.5f);
        }

        SpriteFont timefont;// = PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/TimeFont");
        SpriteFont invader;// = PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/Irken");
        Texture2D target;// = PContentManager.Instance.GetObject<Texture2D>(@"Content/Art/Sprites/Reticle");
        public override void Draw(SpriteBatch p_SpriteBatch, GameTime p_GameTime, Rectangle p_Screen)
        {
            
            base.Draw(p_SpriteBatch, p_GameTime, p_Screen);
         
            TimeStep = (float)p_GameTime.TotalGameTime.TotalSeconds - TurnStart;

            if (TimeStep == 0)
            {
                TestMessage = UTPM.CurrentTeam + "'s Turn";
                AllowInput = false;
                EventManager.GetInstance().AddEvent(ClearText, 1.5f);
            }

            if (UTPM.TotalPlayerCount() > 0 && AllowInput)
            {
                p_SpriteBatch.DrawString(timefont, (SL - TimeStep).ToString("##"), new Vector2(110, 10), TeamManager.Instance.GetTeam(UTPM.CurrentTeam), 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.ScreenText));
            }

            p_SpriteBatch.DrawString(invader, TestMessage, new Vector2(55, 115), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.ScreenText));

            if (!m_ChangeTeam && Game1.Instance.CurrentMenu == null)
            {
                Input_Shoot isc = (UTPM.CurrentAvatar[ComponentType.Holder_Weapon] as Holder_Weapon).Weapon[ComponentType.Input_Shoot] as Input_Shoot;
                if (isc != null && isc.FiringPower != 0)
                {
                    float scale = 1 + 2 * isc.FiringPower / 45;
                    int x, y;
                    x = (int)(Game1.Instance.CurrentViewport.Width / 2);
                    y = (int)(Game1.Instance.CurrentViewport.Height / 2);
                    Vector2 origin = new Vector2(target.Height / 2, target.Width / 2);
                    p_SpriteBatch.Draw(target, new Vector2(x, y), null, Color.White, 0.0f, origin, scale, SpriteEffects.None, DrawLayer.GetLayer(DrawLayer.LayerDepth.ArrowAbovePlayer));
                }
            }
        }

        public PlayerIndex CurrentPlayer()
        {
                return UTPM.CurrentPlayer;
        }

        bool AllowInput = true;
        public void ClearText()
        {
            TestMessage = "";
            AllowInput = true;
        }

        protected override void RemoveObjects()
        {
            bool switch_teams = false;
            if (_RemoveUs.Contains(UTPM.CurrentAvatar))
            {
                switch_teams = true;
            }
            foreach(GameObject po in _RemoveUs)
            {
                if(po is PlayerObject)
                {
                    bool switched_teams = UTPM.RemoveAvatar(po as PlayerObject);
                    if(switched_teams)
                    {
                        FakeSwitchTeam2(LastGameTime, true);
                        switch_teams = false;
                    }
                }
            }
            base.RemoveObjects();

            if (switch_teams && UTPM.PlayerManagers.Count > 0)
            {
                FakeSwitchTeam(LastGameTime, true);
            }
            if(UTPM.PlayerManagers.Count == 0)
            {
                Game1.Instance.AddMenu(new GameOver(Team.NoOneLeft));
                Game1.Instance.EndGame();
            }
        }
    }

}
